<html>
    <head>
        <title>自定义过滤器</title>
    </head>
    <body>
        <script>
              /*
                        四、自定义过滤器  Defining Custom Filters

                                定义 和 实现新新过滤器在很大程度上取决于数据库提供程序。

                                ABP为所有数据库提供程序实现所有预定义的过滤器。

                                如何自定义过滤器：

                                1、第一步：定义过滤器接口：

                                        当你需要自定义过滤器时，首先为你的过滤器定义一个接口 （比如 ISoftDelete 和 IMultiTenant） 并为你的实体实现它。

                                                eg: 
                                                    public interface IIsActice
                                                    {
                                                        bool IsActive {get;set;} // 过滤器功能所依赖的过滤属性(表字段)
                                                    }

                                        这样的 IIsActive 接口可用于过滤 活动/非活动 数据，并且可以由任何实体轻松实现。

                                                eg:
                                                    public class Book : AggregateRoot<Guid>, IIsActive
                                                    {
                                                        public string Name { get; set; }

                                                        public bool IsActive { get; set; } // IIsActive过滤器接口定义的用于过滤的属性
                                                    }



                                2、EF Core 中配置过滤器：

                                        ABP 使用EF Core 的 "全局查询过滤系统" 来集成过滤器(预定义 / 自定义 )

                                        因此，即使你直接使用DbContext，它也可以很好地继承到EF Core 并按预期工作。

                                        实现自定义过滤器的最佳方法是为 DbContext 重写 "ShouldFilterEntity" 和 "CreateFilterExpression" 这连个方法：

                                            eg:

                                                // 查看全局配置，是否IsActive过滤器被配置为启用状态
                                                // 添加了IsActiveFilterEnabled属性来检查IIsActive是否启用。它在内部使用之前介绍的IDataFilter服务。
                                                protected bool IsActiveFilterEnabled => DataFilter?.IsEnabled<IIsActive>() ?? false;

                                                // 重写ShouldFilterEntity方法
                                                protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType)
                                                {
                                                    // 检查给定实体是否实现了IIsActive接口
                                                    if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity)))
                                                    {
                                                        return true;
                                                    }

                                                    return base.ShouldFilterEntity<TEntity>(entityType);
                                                }

                                                // 配置过滤器表达式
                                                protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>(ModelBuilder modelBuilder)
                                                {
                                                    // 创建基本表达式树，如果存在的话
                                                    var expression = base.CreateFilterExpression<TEntity>(modelBuilder);

                                                    if (typeof(IIsActive).IsAssignableFrom(typeof(TEntity))) // 检查给定实体是否实现了IIsActive接口
                                                    {
                                                        // 构建过滤器表达式树
                                                        Expression<Func<TEntity, bool>> isActiveFilter = e => !IsActiveFilterEnabled || EF.Property<bool>(e, "IsActive");
                                                        expression = expression == null ? isActiveFilter : QueryFilterExpressionHelper.CombineExpressions(expression, isActiveFilter);
                                                    }

                                                    return expression;
                                                }

                                                添加了IsActiveFilterEnabled属性来检查IIsActive是否启用。它在内部使用之前介绍的IDataFilter服务。

                                                覆盖了ShouldFilterEntity和CreateFilterExpression方法，检查给定实体是否实现了IIsActive接口，并在必要时组合表达式。


                                    ★、OnModelCreating方法中配置自定义过滤器：

                                               你可以使用HasAbpQueryFilter 为实体设置过滤器。它将你的过滤器与 ABP EF Core内置的全局过滤器相结合 (And 关系)
                                               
                                                    eg:
                                                            protected override void OnModelCreating(ModelBuilder modelBuilder)
                                                            {
                                                                base.OnModelCreating(modelBuilder);
                                                                
                                                                modelBuilder.Entity<MyEntity>(b =>
                                                                {
                                                                    b.HasAbpQueryFilter(e => e.Name.StartsWith("abp"));
                                                                });
                                                            }
                    */
        </script>
    </body>
</html>